/**
 * 课程表维护脚本；
 * 课程表最多写入30天；
 * 实现：
 * 1. 根据教师课程表，给所有教师安排30天内的课程表池。
 * 2. 根据班级信息将老师已经安排的教师课程表写入课程表池中；
 * 3. 上限都为30天内。
 * 4. 教师课程表为教师自己的课程表，包括已预定课和未预定课。
 * 5. 课程表池为平台的大的课程表信息，包括所有教师课程信息。
 */

var model = require('../model/');
var classModel = model.get('Class');
var TeacherSchedule = model.get('TeacherSchedule');
var ScheduleModel = model.get('Schedule');
var schedule = require('node-schedule')
var blueBird = require('bluebird')

const CLASSTIME = 30 * 60 * 1000;  // 一节课堂所用时间； 
const DAYMILLISECOND = 24 * 60 * 60 * 1000;  // 一天时间的毫秒数；

// 30天内遍历函数
const map30Days = (cb) => {
    const today = new Date();
    for (let i = 0; i < 30; i++) {
        let day = new Date(today.getTime() + i * DAYMILLISECOND);
        let dateInfo = {
            day,
            year : day.getFullYear(),
            month : day.getMonth(),
            days : day.getDate(),
            weekDay : day.getDay() || 7
        };
        const result = cb(dateInfo);
        result === false && break;
    }
}

// 获取插入课表池的上课时间
async function getScheduleStartTimeByClass(classObj) {
    let {start, classTimes, totalCourses, progress, name} = classObj,
        times = [], today = new Date(),
        dayMillisecond = 24 * 60 * 60 * 1000;
    let filter = {start: {$get: today}, className, name};
    // 按星期排序
    classTimes.sort((obj1, obj2) => obj1.dayOfWeek - obj2.dayOfWeek);

    try {
        // 查看今天以后所有班级课程
        let schedules = await ScheduleModel.find(filter);
        let count = schedules.length;
        // 计算出可以添加条数（目的是添加课程不超出班级总课时）
        let addCount = totalCourses - progress - count;
        // 遍历30天内，计算出所有可以添加的开课时间。
        map30Days((dateInfo) => {
            const {day, year, month, days, weekDay} = dateInfo;
            const dayClassTimes = classTimes.filter(item => item.dayOfWeek === dateInfo.weekDay);
            if (day < start) {
                return;
            }
            if (dayClassTimes.length) {
                for (let classTimeObj of dayClassTimes) {
                    if (addCount-- <= 0) {
                        let time = new Date(year, month, days, classTimeObj.startHour, classTimeObj.startMinute);
                        times.push(time);
                    } else {
                        return false;
                    }
                }
            }
        })
        return times;
    } catch(e) {
        console.log(e);
        return [];
    }
} 

// 获取教师某一课表在未来30天内需要更新的数组。
async function getScheduleStartTimeByTeacher(teacherSchedule) {
    const {dayOfWeek, startHour, startMinute, teacherId} = teacherSchedule,
        times = [];
    const today = new Date(),
        dayMillisecond = 24 * 60 * 60 * 1000,
        todayOfWeek = today.getDay() || 7,
        dayDiff = 0,
        year = today.getFullYear(),
        month = today.getMonth(),
        days = today.getDate();

    const filter = {start: {$get: today}, teacherId};
    try {
        const schedules = await ScheduleModel.find(filter);

        const hasdTimeBySchedules = (time) => {
            return schedules.some(schedule => {
                return schedule.start.getTime() === time.getTime();
            })
        }

        if (todayOfWeek < dayOfWeek) {
            dayDiff = dayOfWeek - todayOfWeek;
        } else {
            dayDiff = dayOfWeek + 7 - todayOfWeek;
        }

        while(dayDiff < 30) {
            let time = new Date(yerar, month, days, startHour, startMinute);
            if (!hasdTimeBySchedules(time)) {
                times.push(time);
            }
            dayDiff += 7;
        }
        return times;
    } catch(e) {
        console.log(e)
        return [];
    }
}

// 根据教师id查找所有教师课程表
async function getTeacherScheduleByTeacherId = (teacherId) => {
    try{
        return await TeacherSchedule.find({teacherId});
    } catch(e) {
        console.log(e);
        return [];
    }
}

// 根据教师每一个课程表来更新课程表池。
async function saveScheduleForTeacherSchedule = (teacherSchedule) {
    if (!teacherSchedule._id) {
        return false;
    }

    let teacherScheduleStartTimes = getScheduleStartTimeByTeacher(teacherSchedule);

    if (!teacherScheduleStartTimes.length) {
        console.log('teacherSchedule._id: ' + teacherSchedule._id  + ' 该教师课程表不需要更新');
        return false;
    }

    let creates = teacherScheduleStartTimes.map(start => {
        return {
            start,
            end: new Date(start.getTime() + CLASSTIME)
            teacherId: teacherSchedule.teacherId
        }
    })

    try {
        const result = await Schedule.insertMany(creates);
        return true;
    } catch(err => {
        console.log('saveScheduleForTeacher Schedule.insertMany fail. err = ' + err);
        return false;
    })
}

// 需要更新课表的教师id
async function getTeacherIds = () => {
    try {
        const allTeacherSchedules = await TeacherSchedule.find({});
        return allTeacherSchedules.reduce((teacherIdArr, teacherSchedule) => {
            const teacherId = teacherSchedule._id.toString();
            if (teacherIdArr.indexOf(teacherId) === -1) {
                teacherIdArr.push(teacherId);
            }
            return teacherIdArr;
        }, []);
    } catch (e) {
        console.log(e);
        return [];
    }
}

module.exports = {
    run() {
        // 凌晨2点跑脚本
        var rule    = new schedule.RecurrenceRule();
        rule.hour   = 2;
        rule.minute = 0;

        schedule.scheduleJob(rule, function(){
            var line = "---------------------"
            console.log(line + "定时任务开始" + line)
            
            this.saveScheduleForTeacher(getTeacherIds());
            this.saveScheduleForClass();

        });
    },
    // 班级课程表建立
    saveScheduleForClass(classObj, cb) {
        
        let scheduleStartTimes = getScueduleStartTime(classObj);

    },
    saveScheduleForTeacher(teacherId, cb) {
        if(Object.prototype.toString.call(teacehrId) === '[object Array]') {
            teacherId.map(teacherId => {
                const teacherSchedules = getTeacherScheduleByTeacherId(teacherId);

                teacherSchedules.map(item => saveScheduleForTeacherSchedule(item));
            })
        } else {
            const teacherSchedules = getTeacherScheduleByTeacherId(teacherId);

            teacherSchedules.map(item => saveScheduleForTeacherSchedule(item));
        }
        
        typeof cb === 'function' && cb();
    }
}

